//==========================================================================
// Copyright (c) 2000-2006,  Elastos, Inc.  All Rights Reserved.
//==========================================================================

#if _MSC_VER > 1000
#pragma once
#endif

#if !defined(__AURA_INTERLOCKED_H__)
#define __AURA_INTERLOCKED_H__

#include "_atomic.h"

// The Interlocked class provides the mechanism for synchronizing
// access to a variable that is shared by multiple threads.
// The threads of different processes can use this mechanism
// if the variable is in shared memory.
//
class Interlocked                   // class of atomic operations
{
public:
    Aura_Int32 Increment();               // increase m_addend by one
    Aura_Int32 Decrement();               // decrease m_addend by one
    Aura_Int32 Exchange(Aura_Int32 value);      // swap m_addend with 'value'
    Aura_Int32 ExchangeAdd(Aura_Int32 value);   // increase m_addend by 'value' amount
    Aura_Int32 CompareExchange(Aura_Int32 xchg, Aura_Int32 cmp);  // conditional swapping

    operator Aura_Int32() const { return m_addend; }  // type conversions

    Interlocked() : m_addend(0) { }

private:
    Aura_Int32 m_addend;
};

//==========================================================================
// Interlocked inline functions
//

// The Interlocked::Increment function atomically increments
// (increases by one) the value of the specified variable.
// The return value is the resulting incremented value.
//
INLINE Aura_Int32 Interlocked::Increment()
{
    return interlocked_inc ((long volatile*)&m_addend);
}

// The Interlocked::Decrement function atomically decrements
// (decreases by one) the value of the specified variable.
// The return value is the resulting decremented value.
//
INLINE Aura_Int32 Interlocked::Decrement()
{
    return interlocked_dec((long volatile*)&m_addend);
}

// The Interlocked::Exchange function atomically exchanges a pair of values.
// The function returns the initial value of the specified variable.
//
INLINE Aura_Int32 Interlocked::Exchange(Aura_Int32 value)
{
    return interlocked_xchg((long volatile*)&m_addend, (long)value);
}

// The Interlocked::ExchangeAdd function performs an atomic addition of
// an increment value to the instance object.  The return value is the
// old value of the object.
//
INLINE Aura_Int32 Interlocked::ExchangeAdd(Aura_Int32 value)
{
    return interlocked_xchg_add((long volatile*)&m_addend, (long)value);
}

// The Interlocked::CompareExchange function performs an atomic comparison
// of the specified values and exchanges the values, based on the outcome of
// the comparison.  Parameter 'cmp' specifies the value to compare to that of
// the instance object.  Parameter 'xchg' specifies the exchange value.
// The return value is the old value of the instance.
//
INLINE Aura_Int32 Interlocked::CompareExchange(Aura_Int32 xchg, Aura_Int32 cmp)
{
    return interlocked_cmpxchg((long volatile*)&m_addend, (long)xchg, (long)cmp);
}

#endif // __AURA_INTERLOCKED_H__
